import sys
import time

import paramiko

from common.constant import win_user, win_password


class SSHClent():
    def __init__(self, host='172.16.122.105', port=2222, username='dpi245', password='Colin0519!', pkey_path=None, timeout=10):
        """
            使用xshell登录机器，对于第一次登录的机器会提示允许将陌生机器加入到host_allow列表中，需要connect前调用，否则可能有异常
        :param host:
        :param port:
        :param username:
        :param password:
        :param timeout:
        """
        self.client = paramiko.SSHClient()
        self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

        if password is not None:
            try:
                self.client.connect(hostname=host, port=port, password=password, timeout=timeout)
            except Exception as e:
                print(f'SSH使用密码方式登录，连接失败，错误日志为：{e}')
        elif pkey_path is not None:
            """使用秘钥登录"""
            try:
                self.pkey=paramiko.RSAKey.from_private_key(pkey_path)
                self.client.connect(hostname=host, port=port, pkey=self.pkey, timeout=timeout)
            except Exception as e:
                print(f'SSH使用秘钥方式登录，连接失败，错误日志为：{e}')

        self.sftp = self.client.open_sftp()

    def run_cmd(self, cmd):
        exec_in, exec_out, exec_err = self.client.exec_command(command=cmd, timeout=5)
        return exec_out, exec_err

    def put_file(self, local_file_path, remote_path):
        try:
            self.sftp.put(localpath=local_file_path, remotepath=remote_path)
        except Exception as e:
            print(f'上传本地文件到远端{remote_path}失败： {e}')

    def get_file(self, put_local_path, from_remote_path):
        try:
            self.sftp.get(remotepath=from_remote_path, localpath=put_local_path)
        except Exception as e:
            print(f'下载远端文件{put_local_path}到本地文件失败： {e}')


    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.sftp.close()
        self.client.close()


def decode_bytes(bytestring, code_type='utf8'):
    return bytestring.decode(code_type)


class SSHInteractive():
    """
        本类用于设计有交互的SSH访问
    """

    def __init__(self, host='10.10.110.10', port=2222, user='dpi245', password='Colin0519!'):
        self.transfer = paramiko.Transport((host, port))
        self.transfer.start_client()
        self.transfer.auth_password(user, password)
        self.channel = self.transfer.open_session()
        self.channel.settimeout(20 * 60)
        self.channel.get_pty(term='vt100',width=1980, height=1200, width_pixels=1980, height_pixels=1200)
        self.channel.invoke_shell()

        self.sftp = self.transfer.open_sftp_client()

    def sshpass_tool_install(self):
        # 安装免密工具
        sshpass_tool_install_line = self.send_interactive_cmd(cmd=f'yum -y install sshpass', sleep_time=10)
        if self.check_command_sucess(sshpass_tool_install_line):
            return True
        return False

    def check_is_sshpass_tool_installed(self, to_install=False):
        tool_search_line = self.send_interactive_cmd(cmd=f'sshpass', sleep_time=2)
        shell_end_line_ready = tool_search_line.split('\n')[-2]
        if 'bash' not in shell_end_line_ready.split()[0]:
            return True
        else:
            if to_install:
                if not self.sshpass_tool_install():
                    print("无法正常按照 sshpass 工具，请检查")
                    return False
                if self.check_is_sshpass_tool_installed():
                    return True
        return False

    def check_command_sucess(self, pipeline_console):
        shell_end_line_ready = pipeline_console.split('\n')[-1]
        if ']#' in shell_end_line_ready and shell_end_line_ready.startswith('[root@'):
            return True
        else:
            return False

    def send_interactive_cmd(self, cmd, bufsize=1024 * 10, sleep_time=0.5):
        # print(f'[当前正在执行的命令为]【{cmd}】')
        cmd_long = self.channel.sendall(cmd + '\r')

        if self.channel.send_ready():
            pass
            # print('--------------')
        # while not self.channel.recv_ready():
        #     time.sleep(0.1)
        # print('cmd_long', cmd_long)
        # 等待shell返回
        time.sleep(sleep_time)

        result = self.channel.recv(bufsize)
        shell_current_cmd_line = decode_bytes(result)
        print(shell_current_cmd_line)
        return shell_current_cmd_line


    def put_file(self, local_file_path, remote_path):
        try:
            self.sftp.put(localpath=local_file_path, remotepath=remote_path)
        except Exception as e:
            print(f'上传本地文件到远端{remote_path}失败： {e}')


    def get_file(self, put_local_path, from_remote_path):
        try:
            self.sftp.get(remotepath=from_remote_path, localpath=put_local_path)
        except Exception as e:
            print(f'下载远端文件{put_local_path}到本地文件失败： {e}')

    def win_ssh_server_start(self):
        import os
        os.system('net start sshd')


    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.transfer.close()
        self.channel.close()

    def close(self):
        self.transfer.close()
        self.channel.close()


def current_time():
    return '_'.join([str(each) for each in tuple(time.localtime()[:-3])])


if __name__ == "__main__":
    # ssh = SSHClent()
    # ssh.run_cmd(cmd='cd /srv/zentao_second_dev')

    # for host_ip in ['172.16.43.' + str(ip) for ip in range(119, 123)]:
    '''
    for host_ip in ['172.16.43.118']:
        with SSHInteractive() as ssi:
            current_cmd_line = ssi.send_interactive_cmd(cmd=f'{host_ip}', sleep_time=8)
            # 判断是否登录
            shell_end_line_ready = current_cmd_line.split('\n')[-1]
            if ']#' in shell_end_line_ready and shell_end_line_ready.startswith('[root@'):
                # 安装免密工具
                sshpass_tool_install_line = ssi.send_interactive_cmd(cmd=f'yum -y install sshpass', sleep_time=10)
                # 使用禅道数据库查询数据
                cp_jmeter = '/D:/Program Files/apache-jmeter-5.5' # windows的传递方法
                cp_jmeter = 'root@172.16.122.222:/srv/apache-jmeter-5.5' # linux传递方法
                # 新建一个文件夹
                mkdir_cmd_line = ssi.send_interactive_cmd(cmd=f'mkdir -p /usr/local/jmeter55',sleep_time=0.5)
                print(mkdir_cmd_line)
                # mysql_cmd_line = ssi.send_interactive_cmd(cmd='scp -r root@172.16.122.223:/home/mysql* /srv/', sleep=2)
                scp_cmd_line = ssi.send_interactive_cmd(cmd=f'sshpass -p "password" scp -o "StrictHostKeyChecking no" -r {cp_jmeter} /usr/local/jmeter55', sleep_time=20)
                print(scp_cmd_line)

            # 配置文件添加全局Jmeter环境变量
            write_jmeter_config = """cat >> /etc/profile << 'EOF' 
export JMETER_HOME=/usr/local/jmeter55/apache-jmeter-5.5
export CLASSPATH=$JMETER_HOME/lib/ext/ApacheJMeter_core.jar:JMETER_HOME/lib/jorphan.jar:$CLASSPATH
export PATH=$JMETER_HOME/bin:$PATH:$HOME/bin
EOF
            """

            cat_profile_line = ssi.send_interactive_cmd(cmd=write_jmeter_config)
            # 给目录权限
            shell_end_line_ready = cat_profile_line.split('\n')[-1]
            if ']#' in shell_end_line_ready and shell_end_line_ready.startswith('[root@'):
                granted_jmeter_privilege = ssi.send_interactive_cmd(cmd='chmod 777 -R /usr/local/jmeter55')
            # 重启生效
            shell_end_line_ready = granted_jmeter_privilege.split('\n')[-1]
            if ']#' in shell_end_line_ready and shell_end_line_ready.startswith('[root@'):
                source_profile_line = ssi.send_interactive_cmd(cmd='source /etc/profile')

            shell_end_line_ready = source_profile_line.split('\n')[-1]
            if ']#' in shell_end_line_ready and shell_end_line_ready.startswith('[root@'):
                jmeter_check_line = ssi.send_interactive_cmd(cmd='jmeter -v', sleep_time=5)

            shell_end_line_ready = jmeter_check_line.split('\n')[-1]
            if ']#' in shell_end_line_ready and shell_end_line_ready.startswith('[root@'):
                if 'Copyright' in jmeter_check_line:
                    print(f'====================={host_ip} Jmeter 配置成功=====================')
                else:
                    print(f'ERROR====================={host_ip} Jmeter 配置失败=====================')
            '''

    # ssi_list = []
    # # for host_ip in ['172.16.43.' + str(ip) for ip in range(117, 122)]:
    # for host_ip in ['172.16.43.117']:
    #     ssi = SSHInteractive()
    #     current_cmd_line = ssi.send_interactive_cmd(cmd=f'{host_ip}', sleep_time=3)
    #     # 判断是否登录
    #     shell_end_line_ready = current_cmd_line.split('\n')[-1]
    #     if ']#' in shell_end_line_ready and shell_end_line_ready.startswith('[root@'):
    #         ssi_list.append((host_ip,ssi))

    # run_jmeter_script_location = r'/usr/local/jmeter55/apache-jmeter-5.5/bin/136_performance_api/高精地图平台补测/拥堵态势分析服务订阅接口生成接口TPS2.5W压测.jmx'
    # ssi_list = [(0,0)]
    # try:
    #     for each_item in ssi_list:
    #         host = each_item[0]
    #         each_ssi = each_item[1]
    #         jmeter_run_nonGUI_cmd = '/usr/local/jmeter55/apache-jmeter-5.5/bin/jmeter -n -t {jmx} -l {jtl} -e -o /root/report517_{current} &'.format(
    #             jmx=run_jmeter_script_location, jtl=f'/root/交通拥堵态势压测517_{current_time()}.jtl', current=current_time()
    #         )
    #         precess_info = each_ssi.send_interactive_cmd(cmd=jmeter_run_nonGUI_cmd, sleep_time=60)
    #         shell_end_line_ready = precess_info.split('\n')[-1]
    #         if ']#' in shell_end_line_ready and shell_end_line_ready.startswith('[root@'):
    #             print(f'{host} 已在后台运行')
    #         else:
    #             print(f'{host} 执行Jmeter脚本报错，程序未正常运行')
    #             break
        # ------------------------- 清理文件 ---------------------------------------------------
        # for each_item in ssi_list:
        #     host = each_item[0]
        #     each_ssi = each_item[1]
        #     rm_cmd_line = each_ssi.send_interactive_cmd(cmd='rm -rf /root/交通拥堵态势压测517*')
        #     if check_command_sucess(rm_cmd_line):
        #         print(f'{host} 已清理')
        # ------------------------------------------------------------------------------------
    # except Exception:
    #     sys.exit(0)
    # finally:
    #     for each_item in ssi_list:
    #         each_ssi = each_item[1]
    #         each_ssi.close()


    # --------------------------------------------- 运维自动化演练 -------------------------------------------------------
    host_ip = '172.16.122.105'
    remote_user = win_user
    remote_passwd = win_password
    remote_ip = '172.16.150.76'
    remote_dir = r'E:\work_code_c_plus\mytest_project'.replace('\\', '/')
    remote_dir = 'E:/work_code_c_plus/mytest_project/helloWord.cpp'.replace('\\', '/')
    local_dir = '/home/admin/Documents'
    # 远端(相对本机而言)机器文件递归拷贝到本地

    scp_command_from_remote_line = f'sshpass -p "{remote_passwd}" scp -o "StrictHostKeyChecking no" -r {remote_user}@{remote_ip}:/{remote_dir} {local_dir}'
    # 本机文件拷贝到远端机器
    scp_command_to_remote_line = f'sshpass -p "{remote_passwd}" scp -o "StrictHostKeyChecking no" -r {local_dir} {remote_user}@{remote_ip}:{remote_dir}'
    with SSHInteractive() as ssi:
        try:
            current_cmd_line = ssi.send_interactive_cmd(cmd=f'{host_ip}', sleep_time=4.5)
            # assert ssi.check_is_sshpass_tool_installed(to_install=True), '工具检查失败, 无法做如下的操作'
            if ssi.check_command_sucess(current_cmd_line):
                scp_cmd_line = ssi.send_interactive_cmd(
                    cmd=scp_command_from_remote_line,
                    sleep_time=5)
                execute_shell_script_cmd_line = ssi.send_interactive_cmd(
                    cmd='cd $Dashboard && bash utils/restart_server.sh',
                    sleep_time=10
                )
                execute_shell_script_cmd_line = ssi.send_interactive_cmd(
                    cmd='sshpass -p "0519" ssh laptop-rmarr8k8\\thinkbook@172.16.150.76',
                    sleep_time=10
                )
        except Exception as e:
            print(e)
            sys.exit(-1)
        finally:
            ssi.close()







